﻿using System;
using System.Collections.Generic;
using System.Collections;

using Game.Common;

namespace Game.Command
{
    public class ScheduledCommandQueue : IEnumerable
    {
        public event EventHandler CollectionChanged;

        readonly List<ScheduledCommand> _GameCommands;

        ScheduledCommand _RunningCommand;

        public ScheduledCommandQueue()
        {
            _GameCommands = new List<ScheduledCommand>();
        }

        public void Add(
            CommandExecutor commandExecutor, 
            ScheduledCommand command, 
            GameTurn turn)
        {
            _GameCommands.Add(command);
            _GameCommands.Sort((a, b) => b.Index - a.Index);
            StartNextCommand(commandExecutor, turn);
            FireChanged();
        }

        public void Remove(
            CommandExecutor commandExecutor,
            ScheduledCommand item)
        {
            _GameCommands.Remove(item);
            item.Cancel(commandExecutor);

            if (_RunningCommand == item)
            {
                _RunningCommand = null;
                var turn = GameTurn.Create();
                StartNextCommand(commandExecutor, turn);
            }

            FireChanged();
        }

        void StartNextCommand(
            CommandExecutor commandExecutor,
            GameTurn turn)
        {
            if (_GameCommands.Count == 0)
            {
                return;
            }
            if (_RunningCommand != null)
            {
                return;
            }

            ScheduledCommand scheduled = _GameCommands[_GameCommands.Count-1];
            _RunningCommand = scheduled;

            scheduled.Schedule(commandExecutor);
            commandExecutor.Schedule(turn, scheduled);

            scheduled.Running += OnReady;
        }

        void OnReady(
            object source, 
            ScheduledCommandEventArgs args)
        {
            args.GameCommand.Running -= OnReady;
            _RunningCommand = null;
            _GameCommands.Remove(args.GameCommand);

            GameTurn turn = GameTurn.Create();
            StartNextCommand(args.CommandExecutor, turn);
            FireChanged();
        }

        public int Count
        {
            get { return _GameCommands.Count; }
        }

        public IEnumerator GetEnumerator()
        {
            return _GameCommands.GetEnumerator();
        }

        void FireChanged()
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, new EventArgs());
            }
        }

    }
}
